package com.heima.admin.aspect;


import com.heima.admin.mapper.AdLogMapper;
import com.heima.admin.mapper.AdUserMapper;
import com.heima.common.exception.CustException;
import com.heima.model.admin.pojos.AdUser;
import com.heima.model.admin.pojos.AdUserLog;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;

@Slf4j
@Aspect
@Component
public class WebLogAspect {


    @Autowired
    AdUserMapper adUserMapper;
    @Autowired
    AdLogMapper adLogMapper;

    //定义切入点表达式
    @Pointcut("@annotation(com.heima.admin.aspect.WebLog)")
    public void Pointcut(){
    }

    @Around("Pointcut()")
    public Object around(ProceedingJoinPoint joinPoint){
        Object result = null;
        try {
            //记录请求的类名 + 方法名
            MethodSignature methodsignature = (MethodSignature) joinPoint.getSignature();
            //连接点对象 可以得到 Method对象
            Method method = methodsignature.getMethod();
            String methodName = method.getDeclaringClass().getName() + "." + method.getName();
            log.info("记录全路径类名={}",methodName);
            //记录请求的操作
            WebLog webLog = method.getDeclaredAnnotation(WebLog.class);
            String oparation = webLog.value();
            log.info("记录请求操作={}",oparation);
            //记录请求的方式
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            String requestMethod = request.getMethod();
            log.info("记录请求方式={}",requestMethod);
            //记录请求url
            String requestURL = String.valueOf(request.getRequestURL());
            log.info("记录请求url={}",requestURL);
            //方法执行前时间
            long a=System.currentTimeMillis();
            result = joinPoint.proceed();
            log.info("{}方法执行成功",oparation);

            //方法持续时间
            a =(System.currentTimeMillis()-a);
            log.info("记录方法持续时间={}",a);
            //记录操作人（登录用户id）
            Integer id = AppThreadLocalUtils.getUser().getId();
            log.info("记录操作人id={}",id);
            //记录操作人（登录用户）
            AdUser adUser = adUserMapper.selectById(id);
            String userName = adUser.getName();
            log.info("记录操作人={}",userName);
            //记录登录用户IP
            String ip = getIpAddr(request);
            log.info("记录操作人ip={}",ip);
            //设置实体类
            AdUserLog adUserLog = new AdUserLog();
            adUserLog.setMethodName(methodName);
            adUserLog.setRequestMethod(requestMethod);
            adUserLog.setRequestPath(requestURL);
            adUserLog.setRequestOperation(oparation);
            adUserLog.setOperator(userName);
            adUserLog.setOperatorId(id);
            adUserLog.setExecuteTime((int)a);
            adUserLog.setRemoteAddr(ip);
            adUserLog.setCreateTime(new Date());
            adLogMapper.insert(adUserLog);
            log.info("实体类创建成功");
        }catch (Throwable throwable){
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR,"操作日志记录失败");
        }finally {
            log.info("方法执行成功，操作日志记录成功");
        }
        return result;
    }

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.equals("0:0:0:0:0:0:0:1")) {
            ip = "本地";
        }
        return ip;
    }
}
